/****************************************************
	文件：ResConfig.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2021/1/3 1:58:48
	功能：资源配置
*****************************************************/

using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using HTFW.ABBuilder;
using HTFW.Consts;
using HTFW.Core;
using HTFW.Logger;
using HTFW.Utility.Global;
using UnityEngine;

namespace HTFW.Res
{
    public class ResConfig : Singleton<ResConfig>, IDisposable
    {
        Dictionary<string, ResData> mCfg;
        public Dictionary<string, ResData> Cfg => mCfg;

        AssetBundle mCfgAB; //资源配置文件所在的AB包
        TextAsset mCfgTextAsset; //资源配置Asset文件

        public void Init()
        {
            mCfg = new Dictionary<string, ResData>();

            ReadABConfig();
            ReleaseABConfig();
        }

        public void Dispose()
        {
            mCfg = null;
        }

        public void Add(string key, ResData resData)
        {
            if (!mCfg.ContainsKey(key))
            {
                mCfg.Add(key, resData);
            }
        }

        public ResData Get(string key)
        {
            if (mCfg.ContainsKey(key))
            {
                return mCfg[key];
            }

            return null;
        }

        public bool TryGet(string key, out ResData resData)
        {
            if (mCfg.TryGetValue(key, out resData))
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 加载、读取资源配置文件，生成ResData
        /// </summary>
        void ReadABConfig()
        {
            //1.加载 ABConfig
            string cfgABPath = ResUtil.GetABFullPath(ABDefine.CONFIG_ABNAME);
            HLog.Debug($"AB包配置表的AB包资源路径：{cfgABPath}");

            mCfgAB = AssetBundle.LoadFromFile(cfgABPath);
            mCfgTextAsset = mCfgAB.LoadAsset<TextAsset>(ABDefine.CONFIG_ASSET_NAME);

            if (mCfgTextAsset == null)
            {
                HLog.Error($"LoadABConfig error ! AB包配置表（{ABDefine.CONFIG_ASSET_NAME}）不存在，\n路径：{cfgABPath}");
                return;
            }

            AssetBundleConfig cfg;
            using (MemoryStream memoryStream = new MemoryStream(mCfgTextAsset.bytes))
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                cfg = (AssetBundleConfig) binaryFormatter.Deserialize(memoryStream);
            }

            List<string> abNameLst = new List<string>();
            //2.缓存 assetRes
            for (int i = 0; i < cfg.ABDataList.Count; i++)
            {
                ABData abData = cfg.ABDataList[i];
                ResData assetRes = ResClassObjectPool.Instance.SpawnResData();
                assetRes.Crc = abData.Crc; //资源路径对应的Crc
                assetRes.Path = abData.Path;
                assetRes.AssetName = abData.AssetName;
                assetRes.ABName = abData.ABName;
                assetRes.DependencyABNameList = abData.ABDependencyList;
                assetRes.ResType = ResType.Asset;
                assetRes.LoadState = ResLoadState.None;
                assetRes.Init();

                ILoadResult result = ResClassObjectPool.Instance.SpawnResLoadResult();
                result.Init(assetRes);

                Add(assetRes.Path, assetRes);

                //记录所有的 ABName
                if (!abNameLst.Contains(abData.ABName))
                    abNameLst.Add(abData.ABName);
                foreach (string item in abData.ABDependencyList)
                {
                    if (!abNameLst.Contains(item))
                        abNameLst.Add(item);
                }
            }

            //3.缓存 abRes
            foreach (string abName in abNameLst)
            {
                ResData abRes = ResClassObjectPool.Instance.SpawnResData();
                abRes.ABName = abName;
                abRes.Crc = CRC32.GetCrc32(abName);
                abRes.ResType = ResType.AssetBundle;
                abRes.LoadState = ResLoadState.None;
                abRes.Init();
                Add(abRes.ABName, abRes);
            }

            HLog.Info($"AB包配置表加载、缓存完成！共计 {cfg.ABDataList.Count} 个 assetRes , {abNameLst.Count} 个 abRes");
        }

        /// <summary>
        /// 释放资源配置资源
        /// </summary>
        void ReleaseABConfig()
        {
            if (mCfgAB != null)
                mCfgAB.Unload(true);
            mCfgTextAsset = null;
        }
    }
}